/**
* @fileoverview HQ 事件驱动类
* @author zhang jainbin
* @version 1.0
*/



/**
 * 事件驱动对象，包含许多事件驱动以及绑定等方法,关键
 * @namespace
 */
HQ.event = {
	/**
	 * 按键代码映射
	 * @namespace HQ.event.KEYS 里面包含了对按键的映射
	 */
	KEYS: {
		/**
		 * 退格键
		 */
		BACKSPACE: 8,
		/**
		 * tab
		 */
		TAB: 9,
		RETURN: 13,
		ESC: 27,
		SPACE: 32,
		LEFT: 37,
		UP: 38,
		RIGHT: 39,
		DOWN: 40,
		DELETE: 46
	},

	/**
	 * 扩展类型，这类事件在绑定的时候允许传参数，并且用来特殊处理一些特别的事件绑定
	 * @ignore
	 */
	extendType: /(click|mousedown|mouseover|mouseup|mousemove|scroll|contextmenu)/i,
	
	/**
	* 事件绑定
	* @param {DocumentElement} obj 需要添加事件的页面对象
	* @param {String} eventType 需要添加的事件
	* @param {Function} fn 事件需要绑定到的处理函数
	* @param {Array} argArray 参数数组
	* @return  是否绑定成功(true为成功，false为失败)
	* @type Boolean
	* @version 1.0
	* @author zishunchen
	*/
	addEvent: function (obj, eventType, fn, argArray){
		var cfn=fn;
		var res=false;
		if(!obj.eventsList){
			obj.eventsList={};
		}
		if(!obj.eventsList[eventType]){
			obj.eventsList[eventType]={};
		}
		if (HQ.event.extendType.test(eventType)){
			argArray = argArray || [];
			cfn = function(e) {
				fn.apply(null,([HQ.event.getEvent(e)]).concat(argArray));
			};
		}
		if (obj.addEventListener){
		    obj.addEventListener(eventType, cfn, false);
		    res=true;
		} else if (obj.attachEvent){
		    res=obj.attachEvent("on"+eventType, cfn);
		} else {
		    res=false;
		}
		if(res){
			obj.eventsList[eventType][fn.toString()]=cfn;
		}
		return res;
	},
	
	/**
	* 方法取消绑定
	* @param {DocumentElement} obj 需要取消事件绑定的页面对象
	* @param {String} eventType 需要取消绑定的事件
	* @param {Function} fn 需要取消绑定的函数
	* @return  是否成功取消(true为成功，false为失败)
	* @type Boolean
	* @version 1.0
	* @author zishunchen
	*/
	removeEvent: function (obj, eventType, fn){
		var cfn=fn;
		var res=false;
		if(!cfn){
			res=HQ.event.purgeEvent(obj,eventType);
			return res;
		}
		if (HQ.event.extendType.test(eventType) && obj.eventsList[eventType] && obj.eventsList[eventType][fn.toString()]){
			cfn=obj.eventsList[eventType][fn.toString()];
		}

		if (obj.removeEventListener){
			obj.removeEventListener(eventType, cfn, false);
			res=true;
		} else if (obj.detachEvent){
			res= obj.detachEvent("on"+eventType, cfn);
		} else {
			alert("Error.");
		}
		if(res && obj.eventsList[eventType]){
			delete obj.eventsList[eventType][fn.toString()];
		}
		return res;
	},
	
	/**
	* 取消全部某类型的方法绑定
	* @param {DocumentElement} obj 需要取消事件绑定的页面对象
	* @param {String} eventType 需要取消绑定的事件
	* @return {Boolean} 是否成功取消(true为成功，false为失败)
	*/
	purgeEvent:function(obj, type){
		if (obj.eventsList && obj.eventsList[type]) {
			for (var i in obj.eventsList[type]) {
				if (obj.removeEventListener) {
					obj.removeEventListener(type, obj.eventsList[type][i], false);
				}else if (obj.detachEvent) {
					obj.detachEvent('on' + type, obj.eventsList[type][i]);
				}
			}
		}
		if (obj['on' + type]) {
			obj['on' + type] = null;
		}
	},
	
	/**
	 * 根据不同浏览器获取对应的Event对象
	 * @param {Event} evt
	 * @return 修正过的Event对象, 同时返回一个修正button的自定义属性;
	 * @type Event
	 */ 
	getEvent: function (evt){
	    evt = evt || window.event;
	    
	    /*修正Mozilla的event事件*/
        if (!evt && !HQ.userAgent.ie) {
            var c = this.getEvent.caller;
            while (c) {
                evt = c.arguments[0];
                if (evt && Event == evt.constructor) {
                    break;
                }
                c = c.caller;
            }
        }
	    return evt;
	},
	
	/**
	 * 获得鼠标按键
	 * @param {Object} evt
	 * @return {number} 鼠标按键 -1=无法获取event 0=左键 1= 中键 2= 右键
	 */
	getButton: function(evt){
		var e = HQ.event.getEvent(evt);
		if (!e) {
			return -1
		}
		
		if (HQ.userAgent.ie) {
			return e.button - Math.ceil(e.button/2);
		}else{
			return e.button;
		}
	},
	
	/**
	 * 返回事件触发的对象
	 * @param {Object} evt
	 * @return {object}
	 */
	getTarget: function(evt){
		var e = HQ.event.getEvent(evt);
		if (e) {
			return e.target || e.srcElement;
		}else{
			return null;
		}
	},
	
	/**
	 * 返回获得焦点的对象
	 * @param {Object} evt
	 * @return {object}
	 */
	getcurrentTarget: function(evt){
		var e = HQ.event.getEvent(evt);
		if (e) {
			return document.activeElement || e.currentTarget;
		}else{
			return null;
		}
	},
	
	/**
	 * 禁止事件冒泡传播
	 * @param {Event} evt 事件，非必要参数
	 */
	cancelBubble: function(evt){
		evt = HQ.event.getEvent();
		if (!evt) {return false}
		if (evt.stopPropagation) {
			evt.stopPropagation();
		}else{
			if (!evt.cancelBubble) {evt.cancelBubble = true;}
		}
	},

	/**
	 * 取消浏览器的默认事件
	 * @param {Event} evt 事件，非必要参数
	 */
	preventDefault: function(evt){
		evt = HQ.event.getEvent();
		if (!evt) {return false}
		if (evt.preventDefault) {
			evt.preventDefault();
		}else{
			evt.returnValue = false;
		}
	},

	/**
	 * 获取事件触发时的鼠标位置x
	 * @param {Object} evt 事件对象引用
	 */
	mouseX: function(evt){
		evt = HQ.event.getEvent();
		return evt.pageX ||
		(evt.clientX +
		(document.documentElement.scrollLeft || document.body.scrollLeft));
	},

	/**
	 * 获取事件触发时的鼠标位置y
	 * @param {Object} evt 事件对象引用
	 */
	mouseY: function(evt){
		evt = HQ.event.getEvent();
		return evt.pageY ||
		(evt.clientY +
		(document.documentElement.scrollTop || document.body.scrollTop));
	},
	
    /**
     * 将方法绑定在对象上，能够保护this指针不会“漂移”
     * @param {Object} obj 母体对象
     * @param {Object} method 目标方法
     */
    bind: function(obj, method){
        var args = Array.prototype.slice.apply(arguments, [2, arguments.length]);
        return function(){
            var _obj = obj || this;
            var _args = args.slice();
            for (var jj = 0; jj < arguments.length; jj++) {
                _args.push(arguments[jj]);
            }
            if (typeof(method) == "string") {
                if (_obj[method]) {
                    return _obj[method].apply(_obj, _args);
                }
            }
            else {
                return method.apply(_obj, _args);
            }
        }
    }
}

/**
 * 方法同 HQ.event.addEvent
 * @see  HQ.event.addEvent
 */
HQ.event.on = HQ.event.addEvent;
var addEvent=HQ.event.addEvent;
var removeEvent=HQ.event.removeEvent;
var getEvent=HQ.event.getEvent;
